﻿using Kang.ExtendMethod;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using NLog;
using System;
using System.Dynamic;
using System.Diagnostics;
using Kang.Api.Core;

namespace Kang.Api.Filters
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class CheckSignFilterAttribute : Attribute, IActionFilter
    {
        // 控制单个接口是否启用Sign校验
        public bool UseSign { get; set; } = true;

        Logger logger = LogManager.GetCurrentClassLogger();

        public CheckSignFilterAttribute()
        {
        }

        public CheckSignFilterAttribute(bool useSign)
        {
            this.UseSign = useSign;
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            if (Debugger.IsAttached)
            {
                return;
            }
            if (UseSign == false)
            {
                return;
            }
            if (Program.UseSign != true)
            {
                return;
            }
            string path = context.HttpContext.Request.Path;
            string method = context.HttpContext.Request.Method;
            string sign = string.Empty;
            long? t = null;
            if (context.ActionArguments.ContainsKey("sign") && context.ActionArguments.ContainsKey("t"))
            {
                sign = context.ActionArguments["sign"].ToString();
                t = context.ActionArguments["t"].ToString().ToLong();
            }
            else if (context.ActionArguments.ContainsKey("sign") && context.HttpContext.Request.Headers.ContainsKey("t"))
            {
                sign = context.ActionArguments["sign"].ToString();
                t = context.HttpContext.Request.Headers["t"].ToString().ToLong();
            }
            else if (context.HttpContext.Request.Headers.ContainsKey("sign") && context.ActionArguments.ContainsKey("t"))
            {
                sign = context.HttpContext.Request.Headers["sign"].ToString();
                t = context.ActionArguments["t"].ToString().ToLong();
            }
            else if (context.HttpContext.Request.Headers.ContainsKey("sign") && context.HttpContext.Request.Headers.ContainsKey("t"))
            {
                sign = context.HttpContext.Request.Headers["sign"].ToString();
                t = context.HttpContext.Request.Headers["t"].ToString().ToLong();
            }
            string info = $"{method}:{path}  Sign:{sign}  Time:{t}";
            logger.Debug($"{info}");
            dynamic json = new ExpandoObject();
            json.data = null;
            string res = string.Empty;
            ContentResult result = new ContentResult();
            result.ContentType = "application/json";
            result.StatusCode = 200;
            if (sign.IsBlank())
            {
                json.code = 1;
                json.msg = $"签名参数异常";
                result.Content = JsonConvert.SerializeObject(json);
                context.Result = result;
                return;
            }
            if (!t.HasValue)
            {
                json.code = 1;
                json.msg = $"时间戳参数异常";
                result.Content = JsonConvert.SerializeObject(json);
                context.Result = result;
                return;
            }
            if (t.Value <= 0)
            {
                json.code = 1;
                json.msg = $"时间戳参数不能小于等于0";
                result.Content = JsonConvert.SerializeObject(json);
                context.Result = result;
                return;
            }
            var dis = Math.Abs(DateTime.Now.Subtract(t.Value.TimeStampToDateTime().Value).TotalSeconds);
            if (dis > Program.SignTimeLong)
            {
                json.code = 1;
                json.msg = $"接口请求超时";
                result.Content = JsonConvert.SerializeObject(json);
                context.Result = result;
                return;
            }
            var _sign = $"DAKA.INT.{t}.LONG.STRING".MD5Encrypt32().ToUpper();
            if (sign.ToUpper() != _sign)
            {
                json.code = 1;
                json.msg = $"签名验证失败";
                result.Content = JsonConvert.SerializeObject(json);
                context.Result = result;
                return;
            }
        }
    }
}
